package com.swcw.platform.utils;

import java.io.StringReader;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Formatter;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;

import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.input.SAXBuilder;
import org.xml.sax.InputSource;

/**
 * 加密工具
 * 
 * @author 杨坚
 * @version [版本号, 2016年2月22日]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
public class ShareUtils {
	private final static String[] hexDigits = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d",
			"e", "f" };

	public static String create_nonce_str() {
		return UUID.randomUUID().toString();
	}

	public static String getSign(Map<String, Object> map, String key) {
		ArrayList<String> list = new ArrayList<String>();
		for (Map.Entry<String, Object> entry : map.entrySet()) {
			if (entry.getValue() != "") {
				list.add(entry.getKey() + "=" + entry.getValue() + "&");
			}
		}
		int size = list.size();
		String[] arrayToSort = list.toArray(new String[size]);
		Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER);
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < size; i++) {
			sb.append(arrayToSort[i]);
		}
		String result = sb.toString();
		result += "key=" + key;
		System.out.println(result);
		// Util.log("Sign Before MD5:" + result);
		result = MD5Encode(result).toUpperCase();
		// Util.log("Sign Result:" + result);
		return result;
	}

	/**
	 * 请求验证
	 * 
	 * @author 杨坚
	 * @Time 2016年11月11日
	 * @param sign
	 *            标识
	 * @param map
	 *            参数
	 * @param authorizeCode
	 *            鉴权
	 * @return
	 * @throws NoSuchAlgorithmException
	 */
	public static boolean getPlatformSign(Map<String, Object> map, String sign, String authorizeCode)
			throws NoSuchAlgorithmException {
		ArrayList<String> list = new ArrayList<String>();
		for (Map.Entry<String, Object> entry : map.entrySet()) {
			if (entry.getValue() != "") {
				if (!entry.getKey().equals("sign") && !entry.getKey().equals("authorizeCode")
						&& !entry.getKey().equals("bigenPage") && !entry.getKey().equals("endPage")) {
					list.add(entry.getKey() + "=" + entry.getValue() + "&");
				}
			}
		}
		int size = list.size();
		String[] arrayToSort = list.toArray(new String[size]);
		Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER);
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < size; i++) {
			sb.append(arrayToSort[i]);
		}
		String result = sb.toString();
		result += "authorizeCode=" + authorizeCode;
		System.out.println(result);
		result = MD5Encode(result).toUpperCase();
		if (result.equalsIgnoreCase(sign)) {
			return true;
		}
		return false;
	}

	public static String getTimeStamp() {
		return String.valueOf(System.currentTimeMillis() / 1000);
	}

	/**
	 * MD5编码
	 * 
	 * @param origin
	 *            原始字符串
	 * @return 经过MD5加密之后的结果
	 */
	public static String MD5Encode(String origin) {
		String resultString = null;
		try {
			resultString = origin;
			MessageDigest md = MessageDigest.getInstance("MD5");
			md.update(resultString.getBytes("UTF-8"));
			resultString = byteArrayToHexString(md.digest());
		} catch (Exception e) {
			e.printStackTrace();
		}
		return resultString;
	}

	/**
	 * 创建md5摘要,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。
	 */
	@SuppressWarnings("rawtypes")
	public static String createSign(SortedMap<String, String> packageParams, String key) {
		StringBuffer sb = new StringBuffer();
		Set es = packageParams.entrySet();
		Iterator it = es.iterator();
		while (it.hasNext()) {
			Map.Entry entry = (Map.Entry) it.next();
			String k = (String) entry.getKey();
			String v = (String) entry.getValue();
			if (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) {
				sb.append(k + "=" + v + "&");
			}
		}
		sb.append("key=" + key);
		String sign = MD5Util.MD5Encode(sb.toString(), "UTF-8").toUpperCase();
		return sign;

	}

	/**
	 * 转换字节数组为16进制字串
	 * 
	 * @param b
	 *            字节数组
	 * @return 16进制字串
	 */
	public static String byteArrayToHexString(byte[] b) {
		StringBuilder resultSb = new StringBuilder();
		for (byte aB : b) {
			resultSb.append(byteToHexString(aB));
		}
		return resultSb.toString();
	}

	/**
	 * 转换byte到16进制
	 * 
	 * @param b
	 *            要转换的byte
	 * @return 16进制格式
	 */
	private static String byteToHexString(byte b) {
		int n = b;
		if (n < 0) {
			n = 256 + n;
		}
		int d1 = n / 16;
		int d2 = n % 16;
		return hexDigits[d1] + hexDigits[d2];
	}

	/**
	 * 从map数据转换xml
	 * 
	 * @param map
	 * @return
	 */
	@SuppressWarnings("rawtypes")
	public static byte[] callMapToXML(Map map) {

		StringBuffer sb = new StringBuffer();
		sb.append("<xml>");
		mapToXMLTest2(map, sb);
		sb.append("</xml>");
		System.out.println(sb.toString());
		try {
			return sb.toString().getBytes("UTF-8");
		} catch (Exception e) {

		}
		return null;
	}

	@SuppressWarnings("rawtypes")
	private static void mapToXMLTest2(Map map, StringBuffer sb) {
		Set set = map.keySet();
		for (Iterator it = set.iterator(); it.hasNext();) {
			String key = (String) it.next();
			Object value = map.get(key);
			if (null == value)
				value = "";
			if (value.getClass().getName().equals("java.util.ArrayList")) {
				ArrayList list = (ArrayList) map.get(key);
				sb.append("<" + key + ">");
				for (int i = 0; i < list.size(); i++) {
					HashMap hm = (HashMap) list.get(i);
					mapToXMLTest2(hm, sb);
				}
				sb.append("</" + key + ">");

			} else {
				if (value instanceof HashMap) {
					sb.append("<" + key + ">");
					mapToXMLTest2((HashMap) value, sb);
					sb.append("</" + key + ">");
				} else {
					sb.append("<" + key + ">" + value + "</" + key + ">");
				}

			}

		}
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static Map parseXmlToList2(String xml) {
		Map retMap = new HashMap();
		try {
			StringReader read = new StringReader(xml);
			// 创建新的输入源SAX 解析器将使用 InputSource 对象来确定如何读取 XML 输入
			InputSource source = new InputSource(read);
			// 创建一个新的SAXBuilder
			SAXBuilder sb = new SAXBuilder();
			// 通过输入源构造一个Document
			Document doc = (Document) sb.build(source);
			Element root = doc.getRootElement();// 指向根节点
			List<Element> es = root.getChildren();
			if (es != null && es.size() != 0) {
				for (Element element : es) {
					retMap.put(element.getName(), element.getValue());
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return retMap;
	}

	/**
	 * 获取真实的IP4地址
	 * 
	 * @param request
	 * @return
	 */
	public static String getIpAddr(HttpServletRequest request) {
		String ip = request.getHeader("x-forwarded-for");
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("WL-Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getRemoteAddr();
		}
		return ip;
	}

	/**
	 * 解析request信息
	 * 
	 * @param content
	 * @return
	 */
	public static Map<String, String> getPostPara(String content) {
		Map<String, String> paras = new HashMap<String, String>();
		try {
			if (null != content && !"".equals(content)) {
				if (content.indexOf(";") != -1) {
					String[] rs = content.split(";");
					for (int i = 0; i < rs.length; i++) {
						if (rs[i].indexOf("=") == -1) {
							continue;
						}
						String[] temp = rs[i].split("=");
						if (temp.length > 1) {
							String tempStr = temp[1];
							int len = temp.length;
							if (len >= 2) {
								tempStr = "";
								for (int m = 1; m < len; m++) {
									tempStr += temp[m];
								}
							}
							paras.put(temp[0], tempStr);
						}
					}
				} else {
					if (content.indexOf("=") != -1) {
						String[] temp = content.split("=");
						if (temp.length > 1) {
							paras.put(temp[0], temp[1]);
						}
					}
				}

			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return paras;
	}

	/**
	 * 生成JS-SDK权限验证的签名
	 *
	 * @param jsapi_ticket
	 * @param url
	 * @return
	 * @see [类、类#方法、类#成员]
	 */
	public static Map<String, String> sign(String jsapi_ticket, String url) {
		Map<String, String> ret = new HashMap<String, String>();
		String nonce_str = create_nonce_str();
		String timestamp = create_timestamp();

		String string1;
		String signature = "";

		// 注意这里参数名必须全部小写，且必须有序
		string1 = "jsapi_ticket=" + jsapi_ticket + "&noncestr=" + nonce_str + "&timestamp=" + timestamp + "&url=" + url;

		try {
			MessageDigest crypt = MessageDigest.getInstance("SHA-1");
			crypt.reset();
			crypt.update(string1.getBytes("UTF-8"));
			signature = byteToHex(crypt.digest());
		} catch (Exception e) {
			e.printStackTrace();
		}
		ret.put("url", url);
		ret.put("jsapi_ticket", jsapi_ticket);
		ret.put("nonceStr", nonce_str);
		ret.put("timestamp", timestamp);
		ret.put("signature", signature);
		ret.put("string1", string1);
		return ret;

	}

	private static String create_timestamp() {
		return Long.toString(System.currentTimeMillis() / 1000);
	}

	private static String byteToHex(final byte[] hash) {
		Formatter formatter = new Formatter();
		for (byte b : hash) {
			formatter.format("%02x", b);
		}
		String result = formatter.toString();
		formatter.close();
		return result;
	}

	public static void main(String[] args) throws NoSuchAlgorithmException {
		String str = "account=admin&authorizeKey=9f94fe2c2e7d45068ae130dca92d0812&passwd=123456&timestamp=1480295906212&";
		str += "authorizeCode=d230597fa6e04cf875fb6dd4e01b89d9";
		System.out.println(str);

		// JSONObject json = new JSONObject();
		// json.put("authorizeKey", "39d34fddc1a74073a46a16598dd726ea");
		// json.put("authorizeCode", "80B158B7AA122B5EAD18BB49CBC090C9");
		// json.put("passwd", "123456");
		// json.put("telephone", "15951934264");
		// json.put("timestamp", "1479453151");
		// json.put("sign", "4B9CF84CA56A5CAB58CE47E65CAC9B81");
		//
		// getPlatformSign(OwnPlatformTool.jsonToMap(json),
		// "4B9CF84CA56A5CAB58CE47E65CAC9B81",
		// "80B158B7AA122B5EAD18BB49CBC090C9");

	}

}
